Hemirt

Untitled

Jun 24th, 2016
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.30 KB | None | 0 0
  1. /*
  2.  * TeamSpeak 3 client minimal sample with custom
  3.  * capture and record
  4.  *
  5.  * Copyright (c) 2007-2014 TeamSpeak-Systems
  6.  */
  7.  
  8. /* This example connects to a server and plays a wave file, while
  9.    recording incomming sound to output.wav */
  10.  
  11. #ifdef _WIN32
  12. #define _CRT_SECURE_NO_WARNINGS
  13. #pragma warning(disable : 4996)
  14. #include <Windows.h>
  15. #else
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #endif
  20. #include <stdio.h>
  21.  
  22. #include <teamspeak/public_definitions.h>
  23. #include <teamspeak/public_errors.h>
  24. #include <teamspeak/clientlib_publicdefinitions.h>
  25. #include <teamspeak/clientlib.h>
  26.  
  27. #ifdef _WIN32
  28. #define SLEEP(x) Sleep(x)
  29. #else
  30. #define SLEEP(x) usleep(x*1000)
  31. #endif
  32.  
  33. #include "wave.h"
  34.  
  35. /*The client lib works at 48Khz internally.
  36.   It is therefore advisable to use the same for your project */
  37. #define PLAYBACK_FREQUENCY 48000
  38. #define PLAYBACK_CHANNELS 2
  39.  
  40. #define AUDIO_PROCESS_SECONDS 10
  41.  
  42. /*
  43.  * Callback for connection status change.
  44.  * Connection status switches through the states STATUS_DISCONNECTED, STATUS_CONNECTING, STATUS_CONNECTED and STATUS_CONNECTION_ESTABLISHED.
  45.  *
  46.  * Parameters:
  47.  *   serverConnectionHandlerID - Server connection handler ID
  48.  *   newStatus                 - New connection status, see the enum ConnectStatus in clientlib_publicdefinitions.h
  49.  *   errorNumber               - Error code. Should be zero when connecting or actively disconnection.
  50.  *                               Contains error state when losing connection.
  51.  */
  52. void onConnectStatusChangeEvent(uint64 serverConnectionHandlerID, int newStatus, unsigned int errorNumber) {
  53.     printf("Connect status changed: %llu %d %u\n", (unsigned long long)serverConnectionHandlerID, newStatus, errorNumber);
  54.     /* Failed to connect ? */
  55.     if(newStatus == STATUS_DISCONNECTED && errorNumber == ERROR_failed_connection_initialisation) {
  56.         printf("Looks like there is no server running!\n");
  57.     }
  58. }
  59.  
  60. /*
  61.  * Callback for current channels being announced to the client after connecting to a server.
  62.  *
  63.  * Parameters:
  64.  *   serverConnectionHandlerID - Server connection handler ID
  65.  *   channelID                 - ID of the announced channel
  66.  *   channelParentID           - ID of the parent channel
  67.  */
  68. void onNewChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID) {
  69.     /* Query channel name from channel ID */
  70.     char* name;
  71.     unsigned int error;
  72.  
  73.     printf("onNewChannelEvent: %llu %llu %llu\n", (unsigned long long)serverConnectionHandlerID, (unsigned long long)channelID, (unsigned long long)channelParentID);
  74.     if((error = ts3client_getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &name)) == ERROR_ok) {
  75.         printf("New channel: %llu %s \n", (unsigned long long)channelID, name);
  76.         ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
  77.     } else {
  78.         char* errormsg;
  79.         if(ts3client_getErrorMessage(error, &errormsg) == ERROR_ok) {
  80.             printf("Error getting channel name in onNewChannelEvent: %s\n", errormsg);
  81.             ts3client_freeMemory(errormsg);
  82.         }
  83.     }
  84. }
  85.  
  86. /*
  87.  * Callback for just created channels.
  88.  *
  89.  * Parameters:
  90.  *   serverConnectionHandlerID - Server connection handler ID
  91.  *   channelID                 - ID of the announced channel
  92.  *   channelParentID           - ID of the parent channel
  93.  *   invokerID                 - ID of the client who created the channel
  94.  *   invokerName               - Name of the client who created the channel
  95.  */
  96. void onNewChannelCreatedEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  97.     char* name;
  98.  
  99.     /* Query channel name from channel ID */
  100.     if(ts3client_getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &name) != ERROR_ok)
  101.         return;
  102.     printf("New channel created: %s\n", name);
  103.     ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
  104. }
  105.  
  106. /*
  107.  * Callback when a channel was deleted.
  108.  *
  109.  * Parameters:
  110.  *   serverConnectionHandlerID - Server connection handler ID
  111.  *   channelID                 - ID of the deleted channel
  112.  *   invokerID                 - ID of the client who deleted the channel
  113.  *   invokerName               - Name of the client who deleted the channel
  114.  */
  115. void onDelChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  116.     printf("Channel ID %llu deleted by %s (%u)\n", (unsigned long long)channelID, invokerName, invokerID);
  117. }
  118.  
  119. /*
  120.  * Called when a client joins, leaves or moves to another channel.
  121.  *
  122.  * Parameters:
  123.  *   serverConnectionHandlerID - Server connection handler ID
  124.  *   clientID                  - ID of the moved client
  125.  *   oldChannelID              - ID of the old channel left by the client
  126.  *   newChannelID              - ID of the new channel joined by the client
  127.  *   visibility                - Visibility of the moved client. See the enum Visibility in clientlib_publicdefinitions.h
  128.  *                               Values: ENTER_VISIBILITY, RETAIN_VISIBILITY, LEAVE_VISIBILITY
  129.  */
  130. void onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) {
  131.     printf("ClientID %u moves from channel %llu to %llu with message %s\n", clientID, (unsigned long long)oldChannelID, (unsigned long long)newChannelID, moveMessage);
  132. }
  133.  
  134. /*
  135.  * Callback for other clients in current and subscribed channels being announced to the client.
  136.  *
  137.  * Parameters:
  138.  *   serverConnectionHandlerID - Server connection handler ID
  139.  *   clientID                  - ID of the announced client
  140.  *   oldChannelID              - ID of the subscribed channel where the client left visibility
  141.  *   newChannelID              - ID of the subscribed channel where the client entered visibility
  142.  *   visibility                - Visibility of the announced client. See the enum Visibility in clientlib_publicdefinitions.h
  143.  *                               Values: ENTER_VISIBILITY, RETAIN_VISIBILITY, LEAVE_VISIBILITY
  144.  */
  145. void onClientMoveSubscriptionEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility) {
  146.     char* name;
  147.  
  148.     /* Query client nickname from ID */
  149.     if(ts3client_getClientVariableAsString(serverConnectionHandlerID, clientID, CLIENT_NICKNAME, &name) != ERROR_ok)
  150.         return;
  151.     printf("New client: %s\n", name);
  152.     ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
  153. }
  154.  
  155. /*
  156.  * Called when a client drops his connection.
  157.  *
  158.  * Parameters:
  159.  *   serverConnectionHandlerID - Server connection handler ID
  160.  *   clientID                  - ID of the moved client
  161.  *   oldChannelID              - ID of the channel the leaving client was previously member of
  162.  *   newChannelID              - 0, as client is leaving
  163.  *   visibility                - Always LEAVE_VISIBILITY
  164.  *   timeoutMessage            - Optional message giving the reason for the timeout
  165.  */
  166. void onClientMoveTimeoutEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* timeoutMessage) {
  167.     printf("ClientID %u timeouts with message %s\n",clientID, timeoutMessage);
  168. }
  169.  
  170. /*
  171.  * This event is called when a client starts or stops talking.
  172.  *
  173.  * Parameters:
  174.  *   serverConnectionHandlerID - Server connection handler ID
  175.  *   status                    - 1 if client starts talking, 0 if client stops talking
  176.  *   isReceivedWhisper         - 1 if this event was caused by whispering, 0 if caused by normal talking
  177.  *   clientID                  - ID of the client who announced the talk status change
  178.  */
  179. void onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID) {
  180.     char* name;
  181.  
  182.     /* Query client nickname from ID */
  183.     if(ts3client_getClientVariableAsString(serverConnectionHandlerID, clientID, CLIENT_NICKNAME, &name) != ERROR_ok)
  184.         return;
  185.     if(status == STATUS_TALKING) {
  186.         printf("Client \"%s\" starts talking.\n", name);
  187.     } else {
  188.         printf("Client \"%s\" stops talking.\n", name);
  189.     }
  190.     ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
  191. }
  192.  
  193. void onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage) {
  194.     printf("Error for server %llu: %s %s\n", (unsigned long long)serverConnectionHandlerID, errorMessage, extraMessage);
  195. }
  196.  
  197. char* programPath(char* programInvocation){
  198.     char* path;
  199.     char* end;
  200.     int length;
  201.     char pathsep;
  202.  
  203.     if (programInvocation == NULL) return strdup("");
  204.  
  205. #ifdef _WIN32
  206.     pathsep = '\\';
  207. #else
  208.     pathsep = '/';
  209. #endif
  210.  
  211.     end = strrchr(programInvocation, pathsep);
  212.     if (!end) return strdup("");
  213.  
  214.     length = (end - programInvocation) + 2;
  215.     path = (char*)malloc(length);
  216.     strncpy(path, programInvocation, length - 1);
  217.     path[length - 1] = 0;
  218.  
  219.     return path;
  220. }
  221.  
  222. int main(int argc, char** argv) {
  223.     uint64 scHandlerID;
  224.     unsigned int error;
  225.     char *version;
  226.     char *identity;
  227.  
  228.     int    captureFrequency;
  229.     int    captureChannels;
  230.     short* captureBuffer;
  231.     int    captureBufferSamples;
  232.  
  233.     int    audioPeriodCounter;
  234.     int    captureAudioOffset;
  235.     int    capturePeriodSize;
  236.  
  237.     short* playbackBuffer;
  238.     int    playbackAudioOffset;
  239.     int    playbackPeriodSize;
  240.  
  241.     char* path;
  242.  
  243.     /* Create struct for callback function pointers */
  244.     struct ClientUIFunctions funcs;
  245.  
  246.     /* Initialize all callbacks with NULL */
  247.     memset(&funcs, 0, sizeof(struct ClientUIFunctions));
  248.  
  249.     /* Now assign the used callback function pointers */
  250.     funcs.onConnectStatusChangeEvent    = onConnectStatusChangeEvent;
  251.     funcs.onNewChannelEvent             = onNewChannelEvent;
  252.     funcs.onNewChannelCreatedEvent      = onNewChannelCreatedEvent;
  253.     funcs.onDelChannelEvent             = onDelChannelEvent;
  254.     funcs.onClientMoveEvent             = onClientMoveEvent;
  255.     funcs.onClientMoveSubscriptionEvent = onClientMoveSubscriptionEvent;
  256.     funcs.onClientMoveTimeoutEvent      = onClientMoveTimeoutEvent;
  257.     funcs.onTalkStatusChangeEvent       = onTalkStatusChangeEvent;
  258.     funcs.onServerErrorEvent            = onServerErrorEvent;
  259.  
  260.     /* Read in the wave we are going to stream to the server */
  261.     if (!readWave("welcome_to_teamspeak.wav", &captureFrequency, &captureChannels, &captureBuffer, &captureBufferSamples))
  262.         return 1;
  263.    
  264.     /* allocate AUDIO_PROCESS_SECONDS seconds worth of PLAYBACK_FREQUENCY 16bit PLAYBACK_CHANNELS channels */
  265.     playbackBuffer = (short*) malloc(AUDIO_PROCESS_SECONDS * PLAYBACK_FREQUENCY * sizeof(short) * PLAYBACK_CHANNELS);
  266.     if (!playbackBuffer){
  267.         printf("error: could not allocate memory for output wave\n");
  268.         return 1;
  269.     }
  270.  
  271.     /* Initialize client lib with callbacks */
  272.     path = programPath(argv[0]);
  273.     if((error = ts3client_initClientLib(&funcs, NULL, LogType_FILE | LogType_CONSOLE, NULL, path)) != ERROR_ok) {
  274.         char* errormsg;
  275.         if(ts3client_getErrorMessage(error, &errormsg) == ERROR_ok) {
  276.             printf("Error initialzing serverlib: %s\n", errormsg);
  277.             ts3client_freeMemory(errormsg);
  278.         }
  279.         return 1;
  280.     }
  281.  
  282.     /* register a new custom sound device, that captures at read wave freq+channels and plays PLAYBACK_CHANNELS channels at PLAYBACK_FREQUENCY */
  283.     if ((error = ts3client_registerCustomDevice("customWaveDeviceId", "Nice displayable wave device name", captureFrequency, captureChannels, PLAYBACK_FREQUENCY, PLAYBACK_CHANNELS)) != ERROR_ok) {
  284.         char* errormsg;
  285.         if(ts3client_getErrorMessage(error, &errormsg) == ERROR_ok) {
  286.             printf("Error registering custom sound device: %s\n", errormsg);
  287.             ts3client_freeMemory(errormsg);
  288.         }
  289.     }
  290.  
  291.     /* Spawn a new server connection handler using the default port and store the server ID */
  292.     if((error = ts3client_spawnNewServerConnectionHandler(0, &scHandlerID)) != ERROR_ok) {
  293.         printf("Error spawning server connection handler: %d\n", error);
  294.         return 1;
  295.     }
  296.  
  297.     /* Open capture device we created earlier */
  298.     if((error = ts3client_openCaptureDevice(scHandlerID, "custom", "customWaveDeviceId")) != ERROR_ok) {
  299.         printf("Error opening capture device: %d\n", error);
  300.     }
  301.  
  302.     /* Open playback device we created earlier */
  303.     if((error = ts3client_openPlaybackDevice(scHandlerID, "custom", "customWaveDeviceId")) != ERROR_ok) {
  304.         printf("Error opening playback device: %d\n", error);
  305.     }
  306.  
  307.     /* Create a new client identity */
  308.     /* In your real application you should do this only once, store the assigned identity locally and then reuse it. */
  309.     if((error = ts3client_createIdentity(&identity)) != ERROR_ok) {
  310.         printf("Error creating identity: %d\n", error);
  311.         return 1;
  312.     }
  313.  
  314.     /* Connect to server on localhost:9987 with nickname "client", no default channel, no default channel password and server password "secret" */
  315.     if((error = ts3client_startConnection(scHandlerID, identity, "localhost", 9987, "client", NULL, "", "secret")) != ERROR_ok) {
  316.         printf("Error connecting to server: %d\n", error);
  317.         return 1;
  318.     }
  319.  
  320.     ts3client_freeMemory(identity);  /* Release dynamically allocated memory */
  321.     identity = NULL;
  322.  
  323.     printf("Client lib initialized and running\n");
  324.  
  325.     /* Query and print client lib version */
  326.     if((error = ts3client_getClientLibVersion(&version)) != ERROR_ok) {
  327.         printf("Failed to get clientlib version: %d\n", error);
  328.         return 1;
  329.     }
  330.     printf("Client lib version: %s\n", version);
  331.     ts3client_freeMemory(version);  /* Release dynamically allocated memory */
  332.     version = NULL;
  333.  
  334.     SLEEP(500);
  335.  
  336.     printf("\n--- processing audio for %d seconds ---\n", AUDIO_PROCESS_SECONDS);
  337.    
  338.     /*the clientlib works with 20ms packets internaly.
  339.       So the best is to feed is 20ms worth of sound at a time */
  340.     capturePeriodSize = (captureFrequency*20)/1000;
  341.     playbackPeriodSize = (PLAYBACK_FREQUENCY*20)/1000;
  342.  
  343.     captureAudioOffset = 0;
  344.     playbackAudioOffset = 0;
  345.     for(audioPeriodCounter = 0; audioPeriodCounter < 50*AUDIO_PROCESS_SECONDS; ++audioPeriodCounter){ /*50*20=1000*/
  346.         /* wait 20 ms */
  347.         SLEEP(20);
  348.  
  349.         /* make sure we dont stream past the end of our wave sample */
  350.         if (captureAudioOffset + capturePeriodSize > captureBufferSamples)
  351.             captureAudioOffset = 0;
  352.  
  353.         /* stream capture data to the client lib */
  354.         if((error = ts3client_processCustomCaptureData("customWaveDeviceId", captureBuffer + captureAudioOffset*captureChannels, capturePeriodSize)) != ERROR_ok){
  355.             printf("Failed to get stream capture data: %d\n", error);
  356.             return 1;
  357.         }
  358.  
  359.         /* get playback data from the client lib */
  360.         if((error = ts3client_acquireCustomPlaybackData("customWaveDeviceId", playbackBuffer + playbackAudioOffset*PLAYBACK_CHANNELS, playbackPeriodSize))!= ERROR_ok){
  361.             if(error != ERROR_sound_no_data) { //this error signals us to play silence
  362.                 printf("Failed to get acquire playback data: %d\n", error);
  363.                 return 1;
  364.             }
  365.             memset(playbackBuffer + playbackAudioOffset * PLAYBACK_CHANNELS, 0, playbackPeriodSize*2);
  366.         }
  367.  
  368.         /*update buffer offsets */
  369.         captureAudioOffset += capturePeriodSize;
  370.         playbackAudioOffset += playbackPeriodSize;
  371.     }
  372.  
  373.     /* Disconnect from server */
  374.     if((error = ts3client_stopConnection(scHandlerID, "leaving")) != ERROR_ok) {
  375.         printf("Error stopping connection: %d\n", error);
  376.         return 1;
  377.     }
  378.  
  379.     /* Destroy server connection handler */
  380.     if((error = ts3client_destroyServerConnectionHandler(scHandlerID)) != ERROR_ok) {
  381.         printf("Error destroying ServerConnectionHandler: %d\n", error);
  382.         return 1;
  383.     }
  384.  
  385.     /* unregister the custom sound device */
  386.     if ((error = ts3client_unregisterCustomDevice("customWaveDeviceId")) != ERROR_ok){
  387.         printf("Error unregisterring custom sound device: %d\n", error);
  388.         return 1;
  389.     }
  390.  
  391.  
  392.     /* Shutdown client lib */
  393.     if((error = ts3client_destroyClientLib()) != ERROR_ok) {
  394.         printf("Failed to destroy clientlib: %d\n", error);
  395.         return 1;
  396.     }
  397.  
  398.     /* save the playback data */
  399.     writeWave("output.wav", PLAYBACK_FREQUENCY, PLAYBACK_CHANNELS, playbackBuffer, PLAYBACK_FREQUENCY*AUDIO_PROCESS_SECONDS);
  400.  
  401.     /* release allocated memory */
  402.     free(captureBuffer);
  403.     free(playbackBuffer);
  404.  
  405.     return 0;
  406. }
Add Comment
Please, Sign In to add comment